# -*- coding: utf-8 -*-
## This code is responsable for creating visual element structures to support other 3DbyStep routines.
## dispose a group of interations inside these environment.
## Master Research:         Elisabete Thomaselli Nogueira
## Professor:               Claudio Esperanca
## Graduate student:        Victor Soares Bursztyn
## Created in: 07-11-07
## Updated in:  ---
## Last Update: ---

## Class EditableVisualElement defines all transformations and properties (rotation, translation, scale, color, etc) related to visual Elements.

__all__=["EditableVisualElement", "visualElement"]

from OpenGL.GL import *
from OpenGL.GLU import *

from math import sin, cos
from numpy import array, dot
from scene import *
from bbox import *


#class EditableVisualElement(object):
class EditableVisualElement:
    "Base class for graphic objects."

    tx, ty, tz = 0, 0, 0
    rx, ry, rz = 0, 0, 0
    sx, sy, sz = 1.0, 1.0, 1.0
    r = 0.3
    g = 0.6
    b = 0.8
    #color = QtGui.QColor(r, g, b)


    def __init_lx__(self,box,material=None,transformation=None):

        """Constructor.
        @param box: A bounding box for this object.
        @param material: the material object (Material). If None, means that
        no material is attached to this object and thus it will be rendered
        with the current material.
        @param transformation: a transformation (16-float vector). If None,
        then an identity transformation is meant.
        """
        """
        self._box = box
        self.material = material
        self.transformation = transformation
    """

    def _changed (self):
        """Hook for doing bookkeeping whenever a property of the object
        is modified. Derived classes should rewrite this method for its own
        purposes"""
        pass

    def _settransf (self, transformation):
        "Setter for transformation"
        if transformation is None:
            self._transformation = matrix.identity(4)
        else:
            self._transformation = transformation
        self._changed ()

    def _gettransf (self):
        "Getter for transformation"
        return self._transformation

    def _setgrouptransf (self, grouptransformation):
        "Setter for groupo transformation"
        if grouptransformation is None:
            self._grouptransformation = matrix.identity(4)
        else:
            self._grouptransformation = grouptransformation
        self._changed ()

    def _getgrouptransf (self):
        "Getter for group transformation"
        return self._grouptransformation

    def _getbox(self):
        "Getter for box"
        return self._box

    def _setbox(self,box):
        "Setter for box"
        self._box = box
        self._changed()

    transformation = property (_gettransf, _settransf)
    ##?? grouptransformation = property (_getgrouptransf, _setgrouptransf)
    grouptransformation = property (_gettransf, _settransf)

    box = property (_getbox, _setbox)

    def position(self):
        """Returns the translation part of this object's transformation.
        @return: position vector."""
        if self._transformation is not None:
            return self._transformation[3][:3]
        return [0,0,0]


    def __gettransform (self,func,*args):
        """Finds the transformation obtained by composing
        the object's current transformation with the call to some
        function func which affects the current modelview matrix.
        The resulting transformation is stored in self.transformation.

        @param func: a function which affects the current modelview matrix
        (usually glTranslate, glRotate or some such).
        @param args: arguments to be passed to func.
        @return: None.
        """
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()
        func(*args)
        if self._transformation is not None:
            glMultMatrixd(self._transformation)
        self.transformation = glGetDoublev(GL_MODELVIEW_MATRIX)
        glPopMatrix()

    def rotate (self,angle,x,y,z):
        """Alters the object's transformation with the given rotation.
        @param angle: rotation angle in degrees.
        @param x,y,z: rotation axis.
        @return: None.
        """
        self.__gettransform (glRotatef,angle,x,y,z)

    def translate (self,dx,dy,dz):
        """Alters the object's transformation with the given translation.
        @param dx,dy,dz: offset vector.
        @return: None.
        """
        self.__gettransform (glTranslatef,dx,dy,dz)

    ##? 2008-05-05
    def grouptranslate (self,dx,dy,dz):
        """Alters the object's transformation with the given translation.
        @param dx,dy,dz: offset vector.
        @return: None.
        """
        self.__getgrouptransform (glTranslatef,dx,dy,dz)

    def scale (self,dx,dy,dz):
        """Alters the object's transformation with the given scale.
        @param dx,dy,dz: scale factors.
        @return: None.
        """
        self.__gettransform (glScalef,dx,dy,dz)

    #def draw(self):
        """Object's drawing code."""
        #if self.material:
        #    self.material.draw()
        #if self._transformation is not None:
        #    glMultMatrixd(self._transformation)


    def setRotate(self, x, y, z):    ## Errado

        self.rx, self.ry, self.rz = float(x), float(y), float(z)

    def setTranslate(self, x, y, z):

        self.tx, self.ty, self.tz = float(x), float(y), float(z)

    def setScale(self, x, y, z):

        self.sx, self.sy, self.sz = float(x), float(y), float(z)

    def setColor(self, r, g, b):

        self.r, self.g, self.b = float(r/255), float(g/255), float(b/255)

    def setListAnimations(self, animList):
        self.animList = animList

    def setAnimation(self,  animType,  playerExit, initFrame,  lastFrame,  vel, delayTime):
        self.animType = animType
        self.playerExit = playerExit
        self.initFrame = initFrame
        self.lastFrame = lastFrame
        self.vel = vel

    def getTransformation(self):

        transformation_list = []

        transformation_list.append(self.tx)
        transformation_list.append(self.ty)
        transformation_list.append(self.tz)
        transformation_list.append(self.rx)
        transformation_list.append(self.ry)
        transformation_list.append(self.rz)
        transformation_list.append(self.sx)
        transformation_list.append(self.sy)
        transformation_list.append(self.sz)
        #print "teste transformation", tx, ty, tz
        return transformation_list


    def getTransformationMatrix(self):  ## Confirmar como sera o getTransformationMatrix ou transformation

        sinx = sin(self.rx)
        siny = sin(self.ry)
        sinz = sin(self.rz)
        cosx = cos(self.rx)
        cosy = cos(self.ry)
        cosz = cos(self.rz)
        #ScTrMatrix = array([[self.sx, 0, 0, self.tx],[0, self.sy, 0, self.ty],[0, 0, self.sz, self.tz],[0,0,0,1]])
        #RotMatrix = array([[cosy*cosz, cosy*sinz, -siny, 0],[cosz*sinx*siny - cosx*sinz, cosx*cosz + sinx*siny*sinz, cosy*sinx, 0],[cosx*cosz*siny + sinx*sinz, -cosz*sinx + cosx*siny*sinz, cosx*cosy, 0],[0,0,0,1]])
        TMatrix = array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[self.tx,self.ty,self.tz,1]])
        SMatrix = array([[self.sx,0,0,0],[0,self.sy,0,0],[0,0,self.sz,0],[0,0,0,1]])
        RMatrix = array([[cosy*cosz, -cosy*sinz, siny, 0],[sinx*siny*cosz + cosx*sinz,
    -sinx*siny*sinz + cosx*cosz, -sinx*cosy, 0],[-cosx*siny*cosz + sinx*sinz, cosx*siny*sinz + sinx*cosz, cosx*cosy, 0],[0,0,0,1]])
        #RotMatrix = array([[cosy*cosz, cosz*sinx*siny - cosx*sinz, cosx*cosz*siny + sinx*sinz, 0],[cosy*sinz, cosx*cosz + sinx*siny*sinz, -cosz*sinx + cosx*siny*sinz, 0],[-siny, cosy*sinx, cosx*cosy, 0],[0,0,0,1]])
        tempMatrix = dot(RMatrix,SMatrix)
        print "%r", TMatrix
        print "%r", SMatrix
        print "%r", RMatrix
        print "%r", tempMatrix
        transformationMatrix = dot(TMatrix,tempMatrix)
        print "%r", transformationMatrix
        return transformationMatrix

    def getRGB(self):

        RGB = []

        RGB.append(self.r)
        RGB.append(self.g)
        RGB.append(self.b)
        return RGB

    def getCenter(self):

        return self.center + (self.tx, self.ty, self.tz)

    def getSide(self):

        return self.side * (self.sx, self.sy, self.sz)

    def __gettransform (self,func,*args):
        """Finds the transformation obtained by composing
        the object's current transformation with the call to some
        function func which affects the current modelview matrix.
        The resulting transformation is stored in self.transformation.

        @param func: a function which affects the current modelview matrix
        (usually glTranslate, glRotate or some such).
        @param args: arguments to be passed to func.
        @return: None.
        """
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()
        func(*args)
        if self._transformation is not None:
            glMultMatrixd(self._transformation)
        self.transformation = glGetDoublev(GL_MODELVIEW_MATRIX)
        glPopMatrix()

    #************************************************************
    # Group getters and setters
    #************************************************************

    def getGroupNames(self):

        groupNames = []

        for group in self.groups:
            groupNames.append(group.groupName)

        return groupNames

    def getGroupIds(self):

        groupIds = []

        for group in self.groups:
            groupIds.append(group.groupId)

        return groupIds

    def getGroupTransformations(self):

        groupTransformations = []

        for group in self.groups:
            groupTransformations.append(group.getTransformation())

        return groupTransformations

    def getGroupRGBs(self):

        groupRGBs = []

        for group in self.groups:
                groupRGBs.append(group.getRGB())

        return groupRGBs

    def setColor(self, r, g, b):

        for group in self.groups:
                group.setColor(r, g, b)


## *******************************************************************************
## * Calculate objects (or groups) bounding boxes center and site parameters.
## *******************************************************************************
def centersideValues(vet_x, vet_y, vet_z):

    ## Calculate box center and faces, considering object space coordinates to it.
    minx, miny, minz = min(vet_x), min(vet_y), min(vet_z)
    maxx, maxy, maxz = max(vet_x), max(vet_y), max(vet_z)
    if minx < 0:
        if maxx < 0:
            sidex = abs(minx) - abs(maxx)
        else:
          sidex = abs(minx) + maxx
    else:
        sidex = maxx - minx
    centerx = minx + sidex/2.0
    #print "**** vetor em x ", vet_x, **** minx, maxx ", minx, maxx

    if miny < 0:
        if maxy < 0:
            sidey = abs(miny) - abs(maxy)
        else:
            sidey = abs(miny) +  maxy
    else:
        sidey = maxy - miny
    centery = miny + sidey/2.0
    #print "*************** vetor em y ", vet_y, **** miny, maxy ", miny, maxy

    if minz < 0:
        if maxz < 0:
            sidez = abs(minz) - abs(maxz)
        else:
            sidez = abs(minz) + maxz
    else:
        sidez = maxz - minz
    centerz = minz + sidez/2.0
    #print "*************** vetor em z ", vet_z, **** minz, maxz ", minz, maxz

    center = (centerx, centery, centerz)
    side = (sidex, sidey, sidez)

    print "Center: " + str(center)
    print "Side: " + str(side)

    return center, side

## *******************************************************************************
# Define visual element (model, documentation, ...object defaults
## *******************************************************************************
class visualElement(EditableVisualElement):
    """
    ************************************_INIT_******************************************
    Sets up model data.
    @param modelPath: If the *.obj file indicated by "modelPath" is not yet allocated in any visualElement instance, loads the data from file.
    @param modelId: the new visualElement will receive an ID indicated by "modelId".
    @param copyId: if "copyId" differs to -1 it actually indicates the "modelId" that holds the already loaded geometry.
    @param groupNames: "groupNames" will indicate the already known group names contained in the file (in case "copyIndex" differs to -1).
    @param note: "note" will indicate if the element is a 3D canvas to a 2D content held in "modelPath".
    """

    def __init__(self, modelPath, modelId, copyId = -1, groupNames = None, note = False):
        self.note = note
        if note == True:
            self.modelPath = self.objName = modelPath
            self.modelId = modelId
            self.copyId = copyId
            nameSplit = []
            nameSplit = modelPath.split("/")
            self.objName = nameSplit[-1]
            #self.textureId, self.w, self.h = loadImage(modelPath)
            #abrir de modelPath a imagem
            im = Image.open(modelPath)
            im = im.transpose(Image.FLIP_TOP_BOTTOM)
            try:
                ## get image meta-data (dimensions) and data
                self.w, self.h, self.image = im.size[0], im.size[1], im.tostring()
            except SystemError:
                ## has no alpha channel, synthesize one, see the
                ## texture module for more realistic handling
                self.w, self.h, self.image = im.size[0], im.size[1], im.tostring()

            print "self.w, self.h ", self.w, " ", self.h
            self.groups = []
            tempGroup = objGroup(self.modelId, self.modelId + 1, "NoteSingleGroup", 0)
            self.groups.append(tempGroup)
            del tempGroup
        else:
            ## Model file path
            self.modelPath = modelPath
            ## Model Id
            self.modelId = modelId
            ## Specifies if the geometry is already loaded, using the same source file; if it is true,
            ## what modelId contains this information.
            self.copyId = copyId
            ## Group List
            self.groups = []
            ## Model Name
            nameSplit = []
            nameSplit = modelPath.split("/")
            self.objName = nameSplit[-1]
            self.animList = []  ## Lanimista de controle de animações de um objeto.

            if self.copyId == -1:

                ## Vertex coordinates
                self.vx = []
                self.vy = []
                self.vz = []
                ## Normal coordinates
                self.vnx = []
                self.vny = []
                self.vnz = []
                ## Texture coordinates
                self.vtx = []
                self.vty = []
                ## Vertexes, textures and normals coordinates to each face (respectively):
                self.fv  = []
                self.fvt = []
                self.fvn = []
                ## Temporary group instance
                tempGroup = objGroup(self.modelId, self.modelId + 1, "3DbyStepBottomLimit", 0) ##Intern group created to
                ## assure that even models that were not divided into parts during modelling can be drawn group-by-group.
                self.groups.append(tempGroup)
                del tempGroup
                ## Model file
                objFile = open(modelPath, "r")

                line = []

                for line in objFile: ## Reading each line...

                    temp1 = [] ## Temporary variable to manipulate line split
                    temp1 = line.split()

                    if (len(temp1) == 0):
                        continue

                    if(temp1[0]=="v"): ## Reads a vertex coordinate
                        self.vx.append(float(temp1[1]))
                        self.vy.append(float(temp1[2]))
                        self.vz.append(float(temp1[3]))

                    elif(temp1[0]=="vt"): ## Reads a texture coordinate
                        self.vtx.append(float(temp1[1]))
                        self.vty.append(float(temp1[2]))

                    elif(temp1[0]=="vn"): ## Reads a normal coordinate
                        self.vnx.append(float(temp1[1]))
                        self.vny.append(float(temp1[2]))
                        self.vnz.append(float(temp1[3]))

                    elif(temp1[0]=="f"): ## Reads a face
                        self.fv.append([])
                        self.fvt.append([])
                        self.fvn.append([])
                        for i in range(1,len(temp1)):
                                temp2 = [] ## Temporary to manipulate te second split (related to the face description)
                                temp2 = temp1[i].split("/")
                                if (len(temp2) == 2): ## Only one single / as separator?
                                    self.fv[len(self.fv)-1].append(int(temp2[0])-1)
                                    self.fvn[len(self.fvn)-1].append(int(temp2[1])-1)
                                else: ## In case of double / ("//") as separator (either indicating no texture IDs or
                                    ## due to formatting preferences of the tool that generated the *.obj file)
                                    self.fv[len(self.fv)-1].append(int(temp2[0])-1)
                                    if (temp2[1] != ""): ## If there is a non empty texture ID
                                        self.fvt[len(self.fvt)-1].append(int(temp2[1])-1)
                                    self.fvn[len(self.fvn)-1].append(int(temp2[2])-1)
                                del temp2
                        del temp1

                    elif(temp1[0]=="g"): ## Reads a group
                        ## Temporary group instance
                        tempGroup = objGroup(self.modelId, self.modelId + len(self.groups) + 1, str(temp1[1]), len(self.fv))
                        self.groups.append(tempGroup)
                        del tempGroup
                        print ":: Group "+self.groups[-1].groupName+" from face " + str(self.groups[-1].groupStart)
                        print ":: groupId = "+str(self.groups[-1].groupId)

                    else:           ## If the line is empty, due to formatting preferences,
                        continue    ## then advances to the next iteration.

                objFile.close()

                ## Temporary group instance
                tempGroup = objGroup(self.modelId, self.modelId + len(self.groups) + 1, "3DbyStepTopLimit", len(self.fv)) ##Intern group created to
                ## assure that even models that were not divided into parts during modelling can be drawn group-by-group.
                self.groups.append(tempGroup)
                del tempGroup

                ## Calculate box center and faces, considering object space coordinates to it.
                #self.center, self.side = centersideValues(self.vx, self.vy, self.vz)
                self.center, self.side = centersideValues(self.vx, self.vy, self.vz)

                ## Create BoundingBox structure to current object
                self.box = BoundingBox(self.center, self.side)

                for group in range(len(self.groups)-1):             ## Creates bounding boxes to parts, in particular.
                        self.groups[group].createBox(self.vx[self.groups[group].groupStart : self.groups[group+1].groupStart], self.vy[self.groups[group].groupStart : self.groups[group+1].groupStart], self.vz[self.groups[group].groupStart : self.groups[group+1].groupStart])

            else:

                for groupName in groupNames:
                    tempGroup = objGroup(self.modelId, self.modelId + len(self.groups) + 1, groupName, 0)
                    self.groups.append(tempGroup)
                    del tempGroup
                self.objName = self.objName + "(" + str(self.modelId) + ")"


    """
    ************************************_DRAW_******************************************
    Draws visualElement.
    @param selected: "selected" is initially set to -1, which indicates that no group is being selected. However, if it differs to -1, it actually indicates that the model's group with ID equals to "selected" must be shown with more relevance (while the other ones will blend to create an inhibitive effect).
    @param testSelection: "testSelection" is set by default to False, which indicates not to do cursor selection testing. However, if it's set to True, it reutilizes the existing drawing routine to work with the selectionBuffer.
    @param modelTransformation: "modelTransformation" holds the transformations applied to the model, arranged by the form in .getTransformation() method (contained in EditableVisualElement).
    @param groupTransformations: "groupTransformations" holds the list of transformations applied to each model's group, in order and arranged by the form in .getTransformation() method (contained in EditableVisualElement).
    @param groupIds: "groupIds" holds all the model's groups IDs.
    @param groupRGBs: "groupRGBs" holds the list of extra RGB information applied to each model's group.
    """
    #def draw(self, selected = -1, testSelection = False, modelTransformation = None, groupTransformations = None, groupIds = None, groupRGBs = None): ##Draws model with or without group selection handling
    def draw(self, selected = -1, testSelection = False, transformation = None, modelTransformation = None, groupTransformations = None, groupIds = None, groupRGBs = None): ##Draws model with or without group selection handling

        glEnable(GL_DEPTH_TEST)
        glDisable(GL_BLEND)

        ##*************************ModelTransformation***************************
        glPushMatrix()

        glMultMatrixd(transformation)

        ## Tirar depois
        glScalef(modelTransformation[6], modelTransformation[7], modelTransformation[8])
        """
        glRotatef(modelTransformation[3], 1, 0, 0)
        glRotatef(modelTransformation[4], 0, 1, 0)
        glRotatef(modelTransformation[5], 0, 0, 1)
        """

        ## Tirar depois
        glTranslatef(modelTransformation[0], modelTransformation[1], modelTransformation[2])


        if self.note == False:

            for group in range(0, len(self.groups)-1):

                glColor3f(groupRGBs[group][0], groupRGBs[group][1], groupRGBs[group][2])

                ##*************************GroupTransformations***************************
                glPushMatrix()

                glMultMatrixd(transformation)

                glScalef(groupTransformations[group][6], groupTransformations[group][7], groupTransformations[group][8])
                ## Tirar depois
                """
                glRotatef(groupTransformations[group][3], 1, 0, 0)
                glRotatef(groupTransformations[group][4], 0, 1, 0)
                glRotatef(groupTransformations[group][5], 0, 0, 1)
                ## Tirar depois
                """
                glTranslatef(groupTransformations[group][0], groupTransformations[group][1], groupTransformations[group][2])


                if (testSelection == True):
                    glPushName(groupIds[group])

                if (selected != -1):
                    if (groupIds[group] != selected):
                        glEnable(GL_BLEND)
                        glDisable(GL_DEPTH_TEST)
                    else:
                        glEnable(GL_DEPTH_TEST)
                        glDisable(GL_BLEND)
                        self.groups[group].box.draw()

                for i in range(self.groups[group].groupStart, self.groups[group+1].groupStart): ##From the beginning of the current group to the beginning of the next group.
                        if(len(self.fv[i])==1): ## Obs: line and point drawing not yet implemented.
                                continue
                        elif(len(self.fv[i])==2):
                                continue
                        elif(len(self.fv[i])==3):
                                glBegin(GL_TRIANGLES)
                                glNormal3f(self.vnx[self.fvn[i][0]], self.vny[self.fvn[i][0]], self.vnz[self.fvn[i][0]])
                                glVertex3f(self.vx[self.fv[i][0]], self.vy[self.fv[i][0]], self.vz[self.fv[i][0]])
                                glNormal3f(self.vnx[self.fvn[i][1]], self.vny[self.fvn[i][1]], self.vnz[self.fvn[i][1]])
                                glVertex3f(self.vx[self.fv[i][1]], self.vy[self.fv[i][1]], self.vz[self.fv[i][1]])
                                glNormal3f(self.vnx[self.fvn[i][2]], self.vny[self.fvn[i][2]], self.vnz[self.fvn[i][2]])
                                glVertex3f(self.vx[self.fv[i][2]], self.vy[self.fv[i][2]], self.vz[self.fv[i][2]])
                                glEnd()
                        elif(len(self.fv[i])==4):
                                glBegin(GL_QUADS)
                                glNormal3f(self.vnx[self.fvn[i][0]], self.vny[self.fvn[i][0]], self.vnz[self.fvn[i][0]])
                                glVertex3f(self.vx[self.fv[i][0]], self.vy[self.fv[i][0]], self.vz[self.fv[i][0]])
                                glNormal3f(self.vnx[self.fvn[i][1]], self.vny[self.fvn[i][1]], self.vnz[self.fvn[i][1]])
                                glVertex3f(self.vx[self.fv[i][1]], self.vy[self.fv[i][1]], self.vz[self.fv[i][1]])
                                glNormal3f(self.vnx[self.fvn[i][2]], self.vny[self.fvn[i][2]], self.vnz[self.fvn[i][2]])
                                glVertex3f(self.vx[self.fv[i][2]], self.vy[self.fv[i][2]], self.vz[self.fv[i][2]])
                                glNormal3f(self.vnx[self.fvn[i][3]], self.vny[self.fvn[i][3]], self.vnz[self.fvn[i][3]])
                                glVertex3f(self.vx[self.fv[i][3]], self.vy[self.fv[i][3]], self.vz[self.fv[i][3]])
                                glEnd()
                        else:
                                glBegin(GL_POLYGON)
                                for j in range(0,len(self.fv[i])):
                                    glNormal3f(self.vnx[self.fvn[i][j]], self.vny[self.fvn[i][j]], self.vnz[self.fvn[i][j]])
                                    glVertex3f(self.vx[self.fv[i][j]], self.vy[self.fv[i][j]], self.vz[self.fv[i][j]])
                                glEnd()

                        glFlush()

                glPopMatrix() ##***********GroupTransformation**************

                if (testSelection == True):
                    glPopName()

        else: #If note == True
            """
            glBindTexture(GL_TEXTURE_2D, self.textureId)
                #glPixelStorei(GL_UNPACK_ALIGNMENT,1)

            glBegin(GL_QUADS)

            glTexCoord2f(0.0, 0.0)
            glVertex3f(-1.0, -1.0, 3.0)

            glTexCoord2f(1.0, 0.0)
            glVertex3f( 1.0, -1.0, 3.0)

            glTexCoord2f(1.0, 1.0)
            glVertex3f( 1.0,  1.0, 3.0)

            glTexCoord2f(0.0, 1.0)
            glVertex3f(-1.0,  1.0, 3.0)

            glEnd()
            """
            glPixelStorei(GL_UNPACK_ALIGNMENT,1)
            glRasterPos2i(0, 0)
            glDrawPixels(self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE, self.image)

            glFlush()

        glPopMatrix() ##**************ModelTransformation**************

## ************************************************************************************
class objGroup(EditableVisualElement):
## ************************************_INIT_******************************************
    """
    Sets up model's group data.
    @param pId: indicates the group's parent ID, which means basically the ID of the model that contains this group.
    @param gId: is an unique numeric identifier associated to this group.
    @param Name: it's the group's name.
    @param Start: is the index of the face (in the list of the parent's loaded faces) where the group starts.
    """
    def __init__(self, pId, gId, Name, Start):

        self.parentId = pId
        self.groupId = gId
        self.groupName = Name
        self.groupStart = Start

        self.center = (0,0,0)
        self.side = (1,1,1)

    ## *******************************************************************************
    ## * Create bounding boxes to each object group.
    ## *******************************************************************************
    def createBox(self, groupvx, groupvy, groupvz):
          if (len(groupvx)):
              self.center, self.side = centersideValues(groupvx, groupvy, groupvz)
              print "*************Group**************"
              print self.groupName

              self.box = BoundingBox(self.center, self.side)

